#include "StdAfx.h"
#include "FlowGenerator.h"
#include "time.h"

FlowGenerator::FlowGenerator(void)
{		
	orderId = 0;
	map< int, string > vertexMap = map<int,string> ();
	srand((unsigned)time(0));
	graphDesc = GraphDescription();	
}


FlowGenerator::~FlowGenerator(void)
{
}

bool FlowGenerator::tryGenerateNewVertex(string vId){
	if ( !nameOrderMap[vId] ){
		orderId++;
		nameOrderMap[vId] = orderId;
		orderNameMap[orderId] = vId;
		return true;
	} 
	return false;
}


string FlowGenerator::gen_unique_random_string(){
	string vId;
	
	while (true){
		vId = gen_random_string(5);
		if (!nameOrderMap[vId]){
			break;
		}
	}
	return vId;
}

string FlowGenerator::gen_random_string(const int len) {
    static const char alphanum[] =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";
	string s = "";
    for (int i = 0; i < len; ++i) {
        s = s + alphanum[rand() % (sizeof(alphanum) - 1)];
    }
    
	return s;
}


void FlowGenerator::tryAddEdge(int i, int j, int vCount){
	  float basePropability = 1.0;
	  float edgePropability = basePropability * ( 1.0 -  (float)(j -i)/vCount );
	  float randPropability = ((float) rand() / (RAND_MAX+1));	  
	  if (  randPropability < edgePropability ){
		Edge edge;
		edge.start = orderNameMap[i];
		edge.end = orderNameMap[j];
		graphDesc.addVertex(edge);
	}
	return ;
}

GraphDescription FlowGenerator::generateGraph(int cargoAmount, int vertexCount, float propability = 0.5){	
	/*if ( vertexCount < blocks || vertexCount % blocks != 0 ){
		std::cout << "Invalid data" << std::endl;
		return ;
	}*/
	graphDesc.cargoAmount = cargoAmount;
	orderNameMap[0] = "S";
	nameOrderMap["S"] = 0;

	for ( int i =0; i < vertexCount; ++i){
		tryGenerateNewVertex(gen_unique_random_string());
	}
	
	orderNameMap[vertexCount+1] = "T";
	nameOrderMap["T"] = vertexCount+1;
	std::cout << "T count " << vertexCount+1 << std::endl;
	for ( int i =0; i < vertexCount+2; ++i){
		for ( int j =i+1; j < vertexCount+2; ++j){
			tryAddEdge(i, j , vertexCount );
			/*std::cout << orderNameMap[i] << " -> " << orderNameMap[j] << std::endl;*/
		}
	}

	for ( map<string,Vertex>::iterator  it = graphDesc.vertexList.begin(); it != graphDesc.vertexList.end(); it++){
		it->second.inputSum = 0;
		it->second.outputSum = 0;
		
		for ( map<string,int>::iterator eIt = it->second.edges.begin();  eIt != it->second.edges.end(); eIt++){
			eIt->second = 0;
		}

	}
	graphDesc.vertexList["S"].inputSum = cargoAmount;	

	for ( int i =0; i < vertexCount+1; ++i){
		Vertex v = graphDesc.vertexList[orderNameMap[i]];		
		int amount = v.inputSum;			
		//proportional reseource allocation
		while(amount > 0){
			/*std::cout << r << " ";*/
			for ( list<Vertex*>::iterator it = v.nextVertexes.begin() ; ((it != v.nextVertexes.end()) && (amount > 0)); ++it ){
				/*std::cout << "             -----> " <<   (*it)->name << std::endl;*/
				(*it)->edges[v.name]++;
				v.outputSum++;
				(*it)->inputSum++;
				amount--;
			}
		}
		std::cout << v.name << " --> " << v.inputSum <<  " " << v.outputSum << std::endl;
	}

	graphDesc.vertexList["T"].outputSum = graphDesc.vertexList["T"].inputSum;
	std::cout << "T" << " --> " << graphDesc.vertexList["T"].inputSum <<  " " << graphDesc.vertexList["T"].outputSum << std::endl;

	return graphDesc;
	
}
